using System.Collections.Generic;
using Snake.Singleton;
using UnityEngine;

namespace Snake.Grid
{
    public partial class GridManager<TNode> : ISingleton where TNode : IGridNode, new()
    {
        /// <summary>
        /// 逻辑平面
        /// </summary>
        private Plane _plane = new Plane(Vector3.down, 0f);

        /// <summary>
        /// 坐标附加信息
        /// </summary>
        private readonly Dictionary<Vector2Int, TNode> _nodes = new Dictionary<Vector2Int, TNode>();

        public TNode this[Vector2Int point]
        {
            get
            {
                //大于等于min，小于max
                if (!Rect.Contains(point))
                {
                    return default;
                }

                if (_nodes.TryGetValue(point, out var node))
                {
                    return node;
                }

                node = new TNode
                {
                    Point = point
                };
                _nodes.Add(point, node);
                return node;
            }
        }

        public RectInt Rect { get; set; }

        public GridManager(RectInt rect)
        {
            Rect = rect;
        }

        /// <summary>
        /// 获取鼠标所指的世界坐标位置
        /// </summary>
        /// <param name="camera">鼠标视角相机</param>
        /// <returns></returns>
        public Vector2 GetScreenToWorldPoint(Camera camera)
        {
            var ray = camera.ScreenPointToRay(Input.mousePosition);
            _plane.Raycast(ray, out var enter);
            var point = ray.GetPoint(enter);
            return new Vector2(point.x, point.z);
        }

        public bool IsValid(List<Vector2Int> points)
        {
            if (points == null || points.Count == 0)
            {
                return false;
            }

            foreach (var point in points)
            {
                //不在范围内
                if (!Rect.Contains(point))
                {
                    return false;
                }

                //点位无效
                if (!this[point].IsValid)
                {
                    return false;
                }
            }

            return true;
        }

        /// <summary>
        /// 换算中心位置坐标
        /// </summary>
        /// <param name="points"></param>
        /// <returns></returns>
        public Vector3 GetPointsCenterPosition(List<Vector2Int> points)
        {
            var position = Vector3.zero;
            foreach (var point in points)
            {
                position.x += point.x;
                position.z += point.y;
            }

            position.x /= points.Count;
            position.z /= points.Count;

            return position;
        }
    }
}